#include <QMetaObject>
#include <QMetaProperty>
#include "oxford-word.h"
#include "json-serializator.h"
#include "json-deserializator.h"
#include "serializator.h"
#include "deserialization-error.h"

using namespace Oxford;

Word::Word() : Serializable()
{
    qRegisterMetaType< Word >("Oxford::Word");
    qRegisterMetaType< QList<WordUsageExample> >("QList<WordUsageExample>");
    qRegisterMetaType< QList<WordUsageVariant> >("QList<WordUsageVariant>");
    qRegisterMetaType< QList<WordIdiom> >("QList<WordIdiom>");
}

Word::Word(const Word& other) : Serializable(other)
{
    qRegisterMetaType< Word >("Oxford::Word");
    qRegisterMetaType< QList<WordUsageExample> >("QList<WordUsageExample>");
    qRegisterMetaType< QList<WordUsageVariant> >("QList<WordUsageVariant>");
    qRegisterMetaType< QList<WordIdiom> >("QList<WordIdiom>");
}

bool Oxford::Word::isValid() const
{
    return true;
}

ObjectString Word::toString() const
{
    Core::JSONSerializator serializator;
    serializator.beginObject();

    serializator.writeProperty("word", _word);

    serializator.writeProperty("is3000", _is3000);
    serializator.writeProperty("isAcademic", _isAcademic);

    serializator.writeProperty("speechPart", _speechPart);

    serializator.writeProperty("gbTranscription", _gbTranscription);
    serializator.writeProperty("gbPronunciation", _gbPronunciation);
    serializator.writeProperty("usTranscription", _usTranscription);
    serializator.writeProperty("usPronunciation", _usPronunciation);


    serializator.beginList("variants");
    for (int i = 0; i < _variants.count(); i++)
        serializator.writeListItem(QVariant::fromValue(_variants[i].toString()));
    serializator.endList();

    serializator.beginList("idioms");
    for (int i = 0; i < _idioms.count(); i++)
        serializator.writeListItem(QVariant::fromValue(_idioms[i].toString()));
    serializator.endList();

    serializator.endObject();
    return serializator.result();
}



Word Word::fromString(QString data)
{
    Core::JSONDeserializator deserializator(data);

    Word result;
    const QMetaObject* meta = result.metaObject();
    try
    {
        deserializator.beginObject();

        while (!deserializator.atEnd())
        {
            QString propertyName = deserializator.readPropertyName();
            int propertyId = meta->indexOfProperty(propertyName.toStdString().c_str());
            if (propertyId < 0)
                continue;

            Core::IDeserializator::PropertyType propertyType = deserializator.readPropertyType();

            switch (propertyType)
            {
            case Core::IDeserializator::Variant:
                meta->property(propertyId).write(&result, deserializator.readPropertyValue());
                break;

            case Core::IDeserializator::Object:
                break;

            case Core::IDeserializator::List:
                QVariantList list = deserializator.readPropertyValue().toList();

                if (propertyName == "variants")
                {
                    QList<WordUsageVariant> variants;
                    foreach (const QVariant& variant, list)
                        variants << WordUsageVariant::fromString(variant.toString());

                    result._variants = variants;
                }
                else if (propertyName == "idioms")
                {
                    QList<WordIdiom> idioms;
                    foreach (const QVariant& idiom, list)
                        idioms << WordIdiom::fromString(idiom.toString());

                    result._idioms= idioms;
                }
                break;
            }
        }

        deserializator.endObject();
        return result;
    }
    catch (Core::EDeserializationError)
    {
    }
    catch (...)
    {

    }

    return Word();
}





